#include "includes.h"
#include "vpss_impl.h"

MPP_VPSS_GROUP_S *g_stVpssGroups[VPSS_MAX_GRP_NUM];

static pthread_mutex_t vpss_mutex;

int TR_VPSS_Module_Init()
{
    pthread_mutex_init(&vpss_mutex, NULL);
    memset(g_stVpssGroups, 0L, sizeof(g_stVpssGroups));

    return TR_SUCCESS;
}

int TR_VPSS_Module_DeInit()
{
    pthread_mutex_destroy(&vpss_mutex);

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VPSS_CreateGrp(VPSS_GRP VpssGrp, VPSS_GRP_ATTR_S *pstGrpAttr)
{
    int i, chnIdx;
    MPP_VPSS_CHANNEL_S *pstVpssChn;
    MPP_VPSS_GROUP_S *pstVpssGrp;

    if (VpssGrp < 0 || VpssGrp >= VPSS_MAX_GRP_NUM)
        return TR_FAILURE;

    if (g_stVpssGroups[VpssGrp] != NULL)
        return TR_FAILURE;

    pstVpssGrp = (MPP_VPSS_GROUP_S *)calloc(1, sizeof(MPP_VPSS_GROUP_S));
    pstVpssGrp->enModId = TR_ID_VPSS;
    strncpy(pstVpssGrp->strModName, MPP_MOD_VPSS, sizeof(pstVpssGrp->strModName)-1);
    pstVpssGrp->s32DevId = VpssGrp;
    pstVpssGrp->s32MaxChnNum = VPSS_MAX_CHN_NUM;
    pstVpssGrp->enState = VPSS_GRP_STATE_INITED;
    pstVpssGrp->pstChannels = (MPP_VPSS_CHANNEL_S *)calloc(VPSS_MAX_CHN_NUM, sizeof(MPP_VPSS_CHANNEL_S));

    for (chnIdx = 0; chnIdx < VPSS_MAX_CHN_NUM; chnIdx++)
    {
        pstVpssChn = &pstVpssGrp->pstChannels[chnIdx];
        pstVpssChn->bEnable = FALSE;
        pstVpssChn->s32ChnId = i;
        pstVpssChn->u32Depth = 3;
#ifdef USE_SBUFFER
        //init buffer list
        //pstVpssChn->stBufferList = NULL;
        sbuffer_init(&pstVpssChn->stSBuffer);
        sbuffer_alloc(&pstVpssChn->stSBuffer，pstVpssChn->u32Depth * sizeof(VIDEO_FRAME_INFO_S));
#endif
        pstVpssChn->pReversePtr = (void *)&g_stVpssGroups[i];
    }

    memcpy(&pstVpssGrp->stGrpAttr, pstGrpAttr, sizeof(VPSS_GRP_ATTR_S));
    TR_MPI_SYS_PIN_DATA_Init_I(&pstVpssGrp->stPinData, 1, VPSS_MAX_CHN_NUM);

    g_stVpssGroups[VpssGrp] = pstVpssGrp;

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VPSS_DestroyGrp(VPSS_GRP VpssGrp)
{
    int chnIdx;
    MPP_VPSS_CHANNEL_S *pstVpssChn;
    MPP_VPSS_GROUP_S *pstVpssGrp;

    if (VpssGrp < 0 || VpssGrp >= VPSS_MAX_GRP_NUM)
        return TR_FAILURE;

    if (g_stVpssGroups[VpssGrp] == NULL)
        return TR_FAILURE;

    pstVpssGrp = g_stVpssGroups[VpssGrp];

    TR_MPI_SYS_PIN_DATA_DeInit_I(&pstVpssGrp->stPinData);
#ifdef USE_SBUFFER
    //uninit buffer list
    //pstVpssChn->stBufferList = NULL;
    sbuffer_free(&pstVpssChn->stSBuffer);
#endif
    free(pstVpssGrp->pstChannels);
    free(pstVpssGrp);
    g_stVpssGroups[VpssGrp] = NULL;

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VPSS_StartGrp(VPSS_GRP VpssGrp)
{
    if (VpssGrp < 0 || VpssGrp >= VPSS_MAX_GRP_NUM)
        return TR_FAILURE;

    if (g_stVpssGroups[VpssGrp] == NULL)
        return TR_FAILURE;

    g_stVpssGroups[VpssGrp]->enState = VPSS_GRP_STATE_START;

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VPSS_StopGrp(VPSS_GRP VpssGrp)
{
    if (VpssGrp < 0 || VpssGrp >= VPSS_MAX_GRP_NUM)
        return TR_FAILURE;

    if (g_stVpssGroups[VpssGrp] == NULL)
        return TR_FAILURE;

    g_stVpssGroups[VpssGrp]->enState = VPSS_GRP_STATE_STOP;

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VPSS_ResetGrp(VPSS_GRP VpssGrp)
{
    int i, chnIdx;
    MPP_VPSS_CHANNEL_S *pstVpssChn;
    MPP_VPSS_GROUP_S *pstVpssGrp;

    if (VpssGrp < 0 || VpssGrp >= VPSS_MAX_GRP_NUM)
        return TR_FAILURE;

    if (g_stVpssGroups[VpssGrp] == NULL)
        return TR_FAILURE;

    pstVpssGrp = g_stVpssGroups[VpssGrp];
    pstVpssGrp->enState = VPSS_GRP_STATE_STOP;

    for (chnIdx = 0; chnIdx < VPSS_MAX_CHN_NUM; chnIdx++)
    {
        pstVpssChn = &pstVpssGrp->pstChannels[chnIdx];
        pstVpssChn->bEnable = FALSE;
        pstVpssChn->s32ChnId = i;

        //init buffer list
        //pstVpssChn->stBufferList = NULL;

        pstVpssChn->pReversePtr = (void *)&g_stVpssGroups[i];
    }

    TR_MPI_SYS_PIN_DATA_DeInit_I(&pstVpssGrp->stPinData);
    TR_MPI_SYS_PIN_DATA_Init_I(&pstVpssGrp->stPinData, 1, VPSS_MAX_CHN_NUM);

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VPSS_EnableChn(VPSS_GRP VpssGrp, VPSS_CHN s32VpssChnl)
{
    MPP_VPSS_CHANNEL_S *pstVpssChn;
    MPP_VPSS_GROUP_S *pstVpssGrp;

    if (VpssGrp < 0 || VpssGrp >= VPSS_MAX_GRP_NUM)
        return TR_FAILURE;

    if (VpssChn < 0 || VpssChn >= VPSS_MAX_CHN_NUM)
        return TR_FAILURE;

    if (g_stVpssGroups[VpssGrp] == NULL)
        return TR_FAILURE;

    pstVpssGrp = g_stVpssGroups[VpssGrp];
    pstVpssChn = &pstVpssGrp->pstChannels[VpssChn];
    pstVpssChn->bEnable = TRUE;

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VPSS_DisableChn(VPSS_GRP VpssGrp, VPSS_CHN s32VpssChnl)
{
    MPP_VPSS_CHANNEL_S *pstVpssChn;
    MPP_VPSS_GROUP_S *pstVpssGrp;

    if (VpssGrp < 0 || VpssGrp >= VPSS_MAX_GRP_NUM)
        return TR_FAILURE;

    if (VpssChn < 0 || VpssChn >= VPSS_MAX_CHN_NUM)
        return TR_FAILURE;

    if (g_stVpssGroups[VpssGrp] == NULL)
        return TR_FAILURE;

    pstVpssGrp = g_stVpssGroups[VpssGrp];
    pstVpssChn = &pstVpssGrp->pstChannels[VpssChn];
    pstVpssChn->bEnable = FALSE;

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VPSS_GetGrpAttr(VPSS_GRP VpssGrp, VPSS_GRP_ATTR_S *pstGrpAttr)
{
    if (pstGrpAttr == NULL)
        return TR_FAILURE;

    if (VpssGrp < 0 || VpssGrp >= VPSS_MAX_GRP_NUM)
        return TR_FAILURE;

    if (g_stVpssGroups[VpssGrp] == NULL)
        return TR_FAILURE;

    *pstGrpAttr = g_stVpssGroups[VpssGrp]->stGrpAttr;

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VPSS_SetGrpAttr(VPSS_GRP VpssGrp, VPSS_GRP_ATTR_S *pstGrpAttr)
{
    if (pstGrpAttr == NULL)
        return TR_FAILURE;

    if (VpssGrp < 0 || VpssGrp >= VPSS_MAX_GRP_NUM)
        return TR_FAILURE;

    if (g_stVpssGroups[VpssGrp] == NULL)
        return TR_FAILURE;

    g_stVpssGroups[VpssGrp]->stGrpAttr = *pstGrpAttr;

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VPSS_EnableBackupFrame(VPSS_GRP VpssGrp)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_DisableBackupFrame(VPSS_GRP VpssGrp)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_GetChnAttr(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, VPSS_CHN_ATTR_S *pstChnAttr)
{
    MPP_VPSS_CHANNEL_S *pstVpssChn;
    MPP_VPSS_GROUP_S *pstVpssGrp;

    if (pstChnAttr == NULL)
        return TR_FAILURE;

    if (VpssGrp < 0 || VpssGrp >= VPSS_MAX_GRP_NUM)
        return TR_FAILURE;

    if (VpssChn < 0 || VpssChn >= VPSS_MAX_CHN_NUM)
        return TR_FAILURE;

    if (g_stVpssGroups[VpssGrp] == NULL)
        return TR_FAILURE;

    pstVpssGrp = g_stVpssGroups[VpssGrp];
    pstVpssChn = &pstVpssGrp->pstChannels[VpssChn];
    pstChnAttr->u32Width = pstVpssChn->u32Width;
    pstChnAttr->u32Height = pstVpssChn->u32Height;
    pstChnAttr->enPixelFormat = pstVpssChn->enPixelFormat;

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VPSS_SetChnAttr(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, VPSS_CHN_ATTR_S *pstChnAttr)
{
    MPP_VPSS_CHANNEL_S *pstVpssChn;
    MPP_VPSS_GROUP_S *pstVpssGrp;

    if (pstChnAttr == NULL)
        return TR_FAILURE;

    if (VpssGrp < 0 || VpssGrp >= VPSS_MAX_GRP_NUM)
        return TR_FAILURE;

    if (VpssChn < 0 || VpssChn >= VPSS_MAX_CHN_NUM)
        return TR_FAILURE;

    if (g_stVpssGroups[VpssGrp] == NULL)
        return TR_FAILURE;

    pstVpssGrp = g_stVpssGroups[VpssGrp];
    pstVpssChn = &pstVpssGrp->pstChannels[VpssChn];
    pstVpssChn->u32Width = pstChnAttr->u32Width;
    pstVpssChn->u32Height = pstChnAttr->u32Height;
    pstVpssChn->enPixelFormat = pstChnAttr->enPixelFormat;

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VPSS_SetChnParam(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, VPSS_CHN_PARAM_S *pstChnParam)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_GetChnParam(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, VPSS_CHN_PARAM_S *pstChnParam)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_SetGrpParam(VPSS_GRP VpssGrp, VPSS_GRP_PARAM_S *pstVpssParam)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_GetGrpParam(VPSS_GRP VpssGrp, VPSS_GRP_PARAM_S *pstVpssParam)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_SetGrpAdvancedParam(VPSS_GRP VpssGrp, VPSS_NR_ADVANCED_PARAM_S *pstVpssParam)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_GetGrpAdvancedParam(VPSS_GRP VpssGrp, VPSS_NR_ADVANCED_PARAM_S *pstVpssParam)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_SetGrpCrop(VPSS_GRP VpssGrp,  VPSS_CROP_INFO_S *pstCropInfo)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_GetGrpCrop(VPSS_GRP VpssGrp,  VPSS_CROP_INFO_S *pstCropInfo)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_SetChnMode(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, VPSS_CHN_MODE_S *pstVpssMode)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_GetChnMode(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, VPSS_CHN_MODE_S *pstVpssMode)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_SetDepth(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, HI_U32 u32Depth)
{
    MPP_VPSS_CHANNEL_S *pstVpssChn;
    MPP_VPSS_GROUP_S *pstVpssGrp;

    if (VpssGrp < 0 || VpssGrp >= VPSS_MAX_GRP_NUM)
        return TR_FAILURE;

    if (VpssChn < 0 || VpssChn >= VPSS_MAX_CHN_NUM)
        return TR_FAILURE;

    if (g_stVpssGroups[VpssGrp] == NULL)
        return TR_FAILURE;

    pstVpssGrp = g_stVpssGroups[VpssGrp];
    pstVpssChn = &pstVpssGrp->pstChannels[VpssChn];
    pstVpssChn->u32Depth = u32Depth;

    //sbuffer_realloc(&pstVpssChn->stSBuffer，pstVpssChn->u32Depth * sizeof(VIDEO_FRAME_INFO_S));

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VPSS_GetDepth(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, HI_U32 *pu32Depth)
{
    MPP_VPSS_CHANNEL_S *pstVpssChn;
    MPP_VPSS_GROUP_S *pstVpssGrp;

    if (VpssGrp < 0 || VpssGrp >= VPSS_MAX_GRP_NUM)
        return TR_FAILURE;

    if (VpssChn < 0 || VpssChn >= VPSS_MAX_CHN_NUM)
        return TR_FAILURE;

    if (g_stVpssGroups[VpssGrp] == NULL)
        return TR_FAILURE;

    pstVpssGrp = g_stVpssGroups[VpssGrp];
    pstVpssChn = &pstVpssGrp->pstChannels[VpssChn];
    *pu32Depth = pstVpssChn->u32Depth;

    return TR_SUCCESS;
}

//
//1. 统计vpss 绑定chns的所有的分辨率，帧率，分好等级 (不排除会有需要放大的情况)
//2. 做台阶缩放
//3. 从绑定的输出获取buf，

//简单做个版本
//1. 统计vpss 绑定chns的所有的分辨率，分好等级 (org)1080p, 540p, 360p：简单实现：（按像素数）从大到小排序，相同的保留一个，得到一个分辨率台阶数组
//2. 做台阶缩放,缩放到分配好的buf中，
//3. 把做好的buf放入相应的chn buf list中

//1.描述做台阶的等级（分辨率）
//SIZE_S resolution[];
//int reso_count;

//2.获取vb，用于保存缩放后的结果；构建所有台阶缩放任务，统一提交给rga,(提交完成后调用wait_done)
//分配一个VIDEO_FRAME_INFO ,并使用获取到的vb填充对应的成员，

//3.拿到缩放结果vb,根据每个绑定通道的所需帧率，按需丢帧后，把图像帧放入对应的chn buffer list中，vb ref++
//VIDEO_FRAME_INFO frame_info -> buffer list

//4.chn buffer list每拿走一个vb ,还回后 ref--, ref == 0时，vb 还会去给vb池

//暂时不考虑buffer list缓冲深度问题

HI_S32 HI_MPI_VPSS_SendFrame(VPSS_GRP VpssGrp,  VIDEO_FRAME_INFO_S *pstVideoFrame, HI_S32 s32MilliSec)
{
    PIN_DATA_S *pPins;
    MPP_VPSS_CHANNEL_S *pstVpssChn;
    MPP_VPSS_GROUP_S *pstVpssGrp;

    pstVpssGrp = g_stVpssGroups[VpssGrp];
    pPins = &pstVpssGrp->stPinData;

    //1.
    int32_t s32InWidth = pstVideoFrame->stVFrame.u32Width;
    int32_t s32InHeight = pstVideoFrame->stVFrame.u32Height;
    PIXEL_FORMAT_E enInFormat = pstVideoFrame->stVFrame.enPixelFormat;
    assert(pstVideoFrame->stVFrame.enPixelFormat==PIXEL_FORMAT_YUV_SEMIPLANAR_420);

    //SIZE_S step_resolutions[VPSS_MAX_CHN_NUM];
    //int32_t reso_count = 0;
    int i, j;
    int ret;
    MPP_CHANNEL_IMG_INFO_S stImgInfos[VPSS_MAX_CHN_NUM] = {0};
    MPP_CHANNEL_IMG_INFO_S stImgInfosSorted[VPSS_MAX_CHN_NUM] = {0};
    MPP_CHANNEL_IMG_INFO_S stImgInfoTemp;
    int32_t resolution_count = 0;

    //get connected channel's resolution
    for (i = 0; i < pPins->s32OutPinMaxNum; i++)
    {
        if (!pPins->pstOutPins[i].bConnect)
            continue;

        ret = TR_MPI_SYS_Get_Channel_Image_Info(&pPins->pstOutPins[i].stInfo, &stImgInfos[i]);
        if (ret != 0)
        {
            LOG_ERR("TR_MPI_SYS_Get_Channel_Image_Info failed.\n");
            //continue;
        }
    }

    //去重
    for (i = 0; i < VPSS_MAX_CHN_NUM; i++)
    {
        if (!pPins->pstOutPins[i].bConnect)
            continue;

        if (resolution_count == 0)
        {
            stImgInfosSorted[0] = stImgInfos[i];
            resolution_count = 1;
        }
        else
        {
            for (j = 0; j < resolution_count; j++)
            {
                if ((stImgInfosSorted[j].u32Width == stImgInfos[i].u32Width) && (stImgInfosSorted[j].u32Height == stImgInfos[i].u32Height))
                {
                    break;
                }
            }

            if (j >= resolution_count)
            {
                stImgInfosSorted[resolution_count] = stImgInfos[i];
                resolution_count += 1;
            }
        }
    }

    //high -> low, sort resolution
    for (i = resolution_count; i > 1; i--)
    {
        for (j = 0; j < i - 1; j++)
        {
            if ((stImgInfosSorted[j].u32Width*stImgInfosSorted[j].u32Height) <= (stImgInfosSorted[j+1].u32Width*stImgInfosSorted[j+1].u32Height))
            {
                stImgInfoTemp = stImgInfosSorted[j];
                stImgInfosSorted[j] = stImgInfosSorted[j+1];
                stImgInfosSorted[j+1] = stImgInfoTemp;
            }
        }
    }

    //2.获取vb，用于保存缩放后的结果；构建所有台阶缩放任务，统一提交给rga,(提交完成后调用wait_done)
    //分配一个VIDEO_FRAME_INFO ,并使用获取到的vb填充对应的成员，

    VIDEO_FRAME_INFO_S *pstVideoFramesDest = (VIDEO_FRAME_INFO_S *)calloc(resolution_count, sizeof(VIDEO_FRAME_INFO_S));

    VGS_TASK_ATTR_S stTask;
    VIDEO_FRAME_INFO_S stImgIn = *pstVideoFrame;
    VIDEO_FRAME_INFO_S stImgOut;
    VGS_HANDLE hVgsHandle;

    int has_shared = 0;

    ret = TR_MPI_VGS_BeginJob(&hVgsHandle);
    if (ret != 0)
    {
        LOG_ERR("TR_MPI_VGS_BeginJob failed,ret=0x%x\n", ret);
        goto FAILED;
    }

    for (i = 0; i < resolution_count; i++)
    {
        if (i == 0)
        {
            if ((stImgInfosSorted[0].u32Width == s32InWidth) && (stImgInfosSorted[0].u32Height == s32InHeight))
            {
                //pstVideoFramesDest[0] 指向？-> pstVideoFrame
                //有通道需要使用的分辨率与group进来的帧分辨率一样
                //该怎办：
                //1. pstVideoFramesDest[0] = *pstVideoFrame;
                //2. 需要做些处理，以可以共享这块原始视频帧？ vdec 帧？ vi/vvo帧处理还不一样

                has_shared = 1;

                continue;
            }
        }

        pstVideoFramesDest[i].stVFrame.u32Width = stImgInfosSorted[i].u32Width;
        pstVideoFramesDest[i].stVFrame.u32Height = stImgInfosSorted[i].u32Height;
        pstVideoFramesDest[i].stVFrame.enPixelFormat = stImgInfosSorted[i].enPixelFormat;

        uint32_t u32BlkSize = pstVideoFramesDest[i].stVFrame.u32Width * pstVideoFramesDest[i].stVFrame.u32Height * 1.5;
        VB_BLK vbHandle = TR_MPI_VB_GetBlock(VB_INVALID_POOLID, u32BlkSize);
        pstVideoFramesDest[i].stVFrame.u64VBHandle = vbHandle;

        //pstVideoFramesDest[i].stVFrame.u32Stride[0] = stImgInfosSorted[i].u32Width;//16对齐
        //pstVideoFramesDest[i].stVFrame.u32Stride[1] = stImgInfosSorted[i].u32Width;

        pstVideoFramesDest[i].stVFrame.s16OffsetTop = 0;
        pstVideoFramesDest[i].stVFrame.s16OffsetBottom = pstVideoFramesDest[i].stVFrame.u32Height;
        pstVideoFramesDest[i].stVFrame.s16OffsetLeft = 0;
        pstVideoFramesDest[i].stVFrame.s16OffsetRight = pstVideoFramesDest[i].stVFrame.u32Width;

        stImgOut = pstVideoFramesDest[i];

        stTask.stImgIn = stImgIn;
        stTask.stImgOut = stImgOut;
        ret = TR_MPI_VGS_AddScaleTask(hVgsHandle, &stTask);
        if (ret != 0)
        {
            LOG_ERR("TR_MPI_VGS_AddScaleTask failed,ret=0x%x\n", ret);
        }

        stImgIn = stImgOut;
    }

    ret = TR_MPI_VGS_EndJob(hVgsHandle);
    if (ret != 0)
    {
        LOG_ERR("TR_MPI_VGS_EndJob failed,ret=0x%x\n", ret);
        TR_MPI_VGS_CancelJob(hVgsHandle);
        goto FAILED;
    }

    //3.拿到缩放结果vb,根据每个绑定通道的所需帧率，按需丢帧后，把图像帧放入对应的chn buffer list中，vb ref++
    //VIDEO_FRAME_INFO frame_info -> buffer list

    for (i = 0; i < pPins->s32OutPinMaxNum; i++)
    {
        if (!pPins->pstOutPins[i].bConnect)
            continue;

        pstVpssChn = &pstVpssGrp->pstChannels[i];

        for (j = 0; j < resolution_count; j++)
        {
            if ((stImgInfos[i].u32Width == pstVideoFramesDest[j].stVFrame.u32Width) && (stImgInfos[i].u32Height == pstVideoFramesDest[j].stVFrame.u32Height))
            {
                //pstVideoFramesDest[i].stVFrame.u64VBHandle //ref++
                TR_MPI_VB_Inc_Ref(pstVideoFramesDest[j].stVFrame.u64VBHandle);
#ifdef USE_SBUFFER
                char *ptr = NULL;
                sbuffer_getInptr(&pstVpssChn->stSBuffer, &ptr, sizeof(VIDEO_FRAME_INFO_S));
                if (ptr != NULL)
                {
                    memcpy(ptr, &pstVideoFramesDest[j], sizeof(VIDEO_FRAME_INFO_S));
                    sbuffer_putInptr(&pstVpssChn->stSBuffer, ptr, 0);
                }
                else
                {
                    //如果buffer满了如何处理？
                    TR_MPI_VB_Dec_Ref(pstVideoFramesDest[j].stVFrame.u64VBHandle);

                }
#endif
                break;
            }
        }
    }

    //由于pstVideoFramesDest每写入一个buffer list中，vb就ref++了，从list拿出去使用完后ref--,vb内部判断ref==0时即可释放vb回vb池
    //这里对应的是从Vb池中获取vb时的那个TR_MPI_VB_GetBlock
    for (j = 0; j < resolution_count; j++)
    {
        TR_MPI_VB_ReleaseBlock(pstVideoFramesDest[j].stVFrame.u64VBHandle);
    }

    //是需要释放的
    if (pstVideoFramesDest)
        free(pstVideoFramesDest);

    //4.chn buffer list每拿走一个vb ,还回后 ref--, ref == 0时，vb 还会去给vb池

    //暂时不考虑buffer list缓冲深度问题

    return TR_SUCCESS;

FAILED:

    if (pstVideoFramesDest)
        free(pstVideoFramesDest);

    return TR_FAILURE;
}

HI_S32 HI_MPI_VPSS_GetChnFrame(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, VIDEO_FRAME_INFO_S *pstVideoFrame, HI_S32 s32MilliSec)
{
    MPP_VPSS_CHANNEL_S *pstVpssChn;
    MPP_VPSS_GROUP_S *pstVpssGrp;

    if (VpssGrp < 0 || VpssGrp >= VPSS_MAX_GRP_NUM)
        return TR_FAILURE;

    if (VpssChn < 0 || VpssChn >= VPSS_MAX_CHN_NUM)
        return TR_FAILURE;

    if (g_stVpssGroups[VpssGrp] == NULL)
        return TR_FAILURE;

    pstVpssGrp = g_stVpssGroups[VpssGrp];
    pstVpssChn = &pstVpssGrp->pstChannels[VpssChn];
#ifdef USE_SBUFFER
    char *ptr = NULL;
    sbuffer_getOutPtr(&pstVpssChn->stSBuffer, &ptr);

    *pstVideoFrame = *(VIDEO_FRAME_INFO_S *)ptr;

    //这里有点不合规？ VIDEO_FRAME_INFO_S *pstVideoFrame，就无法保存ptr
    sbuffer_putOutPtr(&pstVpssChn->stSBuffer, ptr, 0);
#endif
    return TR_SUCCESS;
}

HI_S32 HI_MPI_VPSS_ReleaseChnFrame(VPSS_GRP VpssGrp, VPSS_CHN VpssChn,  VIDEO_FRAME_INFO_S *pstVideoFrame)
{
    MPP_VPSS_CHANNEL_S *pstVpssChn;
    MPP_VPSS_GROUP_S *pstVpssGrp;

    if (VpssGrp < 0 || VpssGrp >= VPSS_MAX_GRP_NUM)
        return TR_FAILURE;

    if (VpssChn < 0 || VpssChn >= VPSS_MAX_CHN_NUM)
        return TR_FAILURE;

    if (g_stVpssGroups[VpssGrp] == NULL)
        return TR_FAILURE;

    pstVpssGrp = g_stVpssGroups[VpssGrp];
    pstVpssChn = &pstVpssGrp->pstChannels[VpssChn];

    //*pstVideoFrame = *(VIDEO_FRAME_INFO_S *)ptr;

    //sbuffer_putOutPtr(&pstVpssChn->stSBuffer, ptr, 0);

    TR_MPI_VB_Dec_Ref(pstVideoFrame->stVFrame.u64VBHandle);

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VPSS_GetGrpFrame(VPSS_GRP VpssGrp, VIDEO_FRAME_INFO_S *pstVideoFrame, HI_U32 u32FrameIndex)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_ReleaseGrpFrame(VPSS_GRP VpssGrp,  VIDEO_FRAME_INFO_S *pstVideoFrame)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_SetGrpDelay(VPSS_GRP VpssGrp, HI_U32 u32Delay)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_GetGrpDelay(VPSS_GRP VpssGrp, HI_U32 *pu32Delay)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_SetPreScale(VPSS_GRP VpssGrp,VPSS_PRESCALE_INFO_S *pstPreScaleInfo)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_GetPreScale(VPSS_GRP VpssGrp,VPSS_PRESCALE_INFO_S *pstPreScaleInfo)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_SetGrpSizer(VPSS_GRP VpssGrp, VPSS_SIZER_INFO_S *pstVpssSizerInfo)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_GetGrpSizer(VPSS_GRP VpssGrp, VPSS_SIZER_INFO_S *pstVpssSizerInfo)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_SetGrpFrameRate(VPSS_GRP VpssGrp, VPSS_FRAME_RATE_S *pstVpssFrameRate)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_GetGrpFrameRate(VPSS_GRP VpssGrp, VPSS_FRAME_RATE_S *pstVpssFrameRate)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_SetChnOverlay(VPSS_GRP VpssGrp,VPSS_CHN VpssChn, HI_U32 u32OverlayMask)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_GetChnOverlay(VPSS_GRP VpssGrp,VPSS_CHN VpssChn, HI_U32 *pu32OverlayMask)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_EnableUserFrameRateCtrl(VPSS_GRP VpssGrp)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_DisableUserFrameRateCtrl(VPSS_GRP VpssGrp)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_SetPreScaleMode(VPSS_GRP VpssGrp, VPSS_PRESCALE_MODE_E enVpssPreScaleMode)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_GetPreScaleMode(VPSS_GRP VpssGrp, VPSS_PRESCALE_MODE_E* penVpssPreScaleMode)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_AttachVbPool(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, VB_POOL hVbPool)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_DetachVbPool(VPSS_GRP VpssGrp, VPSS_CHN VpssChn)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_SetModParam(VPSS_MOD_PARAM_S *pstModParam)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_GetModParam(VPSS_MOD_PARAM_S *pstModParam)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_SetRotate(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, ROTATE_E enRotate)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VPSS_GetRotate(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, ROTATE_E *penRotate)
{
    return HI_SUCCESS;
}

